#!/usr/bin/env python
# encoding: utf-8
# @author: liusir
# @file: requests_utils.py
# @time: 2022/11/13 9:43 AM
import json
import re

import jsonpath
import requests
import allure
from requests.exceptions import ProxyError
from requests.exceptions import ConnectionError
from requests.exceptions import RequestException
from utlis.config_utils import local_config
from utlis.check_utils import CheckUtils
from utlis.log_utils import logger

class RequestsUtils:
    def __init__(self):
        self.hosts = local_config.HOSTS
        self.session = requests.session()
        self.tmp_variables = {}
    def __get(self,requests_info): # requests_info 为字典格式传入
        try:
            url = self.hosts + requests_info['请求地址']
            # 关联第二部分：查找并替换掉下一个接口中的变量名
            variable_list = re.findall( '\\${\w+}',requests_info['请求参数(get)'])
            for variable in variable_list:
                requests_info['请求参数(get)'] = requests_info['请求参数(get)']\
                    .replace(variable, str(self.tmp_variables[variable[2:-1]]))
            # 头部信息为空 使用三目运算符处理一下
            url_params = json.loads(requests_info['请求参数(get)']) if requests_info['请求参数(get)'] else None
            header_info = json.loads(requests_info['请求头部信息']) if requests_info['请求头部信息'] else None
            response = self.session.get(url = url,
                                        params=url_params,
                                        headers=header_info )
            response.encoding = response.apparent_encoding # 保证响应信息不乱码
            # 关联第一部分：截取上一个响应的值
            if requests_info['取值方式'] == "正则取值":
                value = re.findall(requests_info['取值代码'],response.text)[0]
                self.tmp_variables[requests_info['取值变量']] = value
            elif requests_info['取值方式'] == "jsonpath取值":
                value = jsonpath.jsonpath(response.json(),requests_info['取值代码'])[0]
                self.tmp_variables[requests_info['取值变量']] = value
            result = CheckUtils(response).run_check(requests_info['断言类型'],requests_info['期望结果'])
        except ProxyError as e:
            result = {'code':3,'message':'调用[%s]时发生代理异常，异常原因：%s'%(requests_info['接口名称'],e.__str__()),'check_result':False}
            logger.error( result['message'] )
        except ConnectionError as e:
            result = {'code':3,'message':'调用[%s]时发生链接异常，异常原因：%s' % (requests_info['接口名称'], e.__str__()),'check_result': False}
            logger.error(result['message'])
        except RequestException as e:
            result = {'code':3,'message':'调用[%s]时发生Requests异常，异常原因：%s' % (requests_info['接口名称'], e.__str__()),'check_result': False}
            logger.error(result['message'])
        except Exception as e:
            result = {'code':3,'message':'调用[%s]时发生系统异常，异常原因：%s' % (requests_info['接口名称'], e.__str__()),'check_result': False}
            logger.error(result['message'])
        return result
    def __post(self,requests_info):
        try:
            url = self.hosts + requests_info['请求地址']
            variable_list = re.findall('\\${\w+}', requests_info['请求参数(get)'])
            for variable in variable_list:
                requests_info['请求参数(get)'] = requests_info['请求参数(get)'] \
                    .replace(variable, str(self.tmp_variables[variable[2:-1]]))
            variable_list = re.findall('\\${\w+}', requests_info['请求参数(post)'])
            for variable in variable_list:
                requests_info['请求参数(post)'] = requests_info['请求参数(post)'] \
                    .replace(variable, str(self.tmp_variables[variable[2:-1]]))
            print( requests_info['请求参数(get)'] )
            url_params = json.loads(requests_info['请求参数(get)']) if requests_info['请求参数(get)'] else None
            header_info = json.loads(requests_info['请求头部信息']) if requests_info['请求头部信息'] else None
            response = self.session.post(url = url,
                                         headers=header_info,
                                         params=url_params,
                                         json=json.loads(requests_info['请求参数(post)']))
            response.encoding = response.apparent_encoding
            print( requests_info['取值代码'] )
            print( response.text )
            if requests_info['取值方式'] == "正则取值":
                value = re.findall(requests_info['取值代码'],response.text)[0]
                self.tmp_variables[requests_info['取值变量']] = value
            elif requests_info['取值方式'] == "jsonpath取值":
                value = jsonpath.jsonpath(response.json(),requests_info['取值代码'])[0]
                self.tmp_variables[requests_info['取值变量']] = value
            result = CheckUtils(response).run_check(requests_info['断言类型'],requests_info['期望结果'])
        except ProxyError as e:
            result = {'code':3,'message':'调用[%s]时发生代理异常，异常原因：%s'%(requests_info['接口名称'],e.__str__()),'check_result':False}
            logger.error(result['message'])
        except ConnectionError as e:
            result = {'code':3,'message':'调用[%s]时发生链接异常，异常原因：%s' % (requests_info['接口名称'], e.__str__()),'check_result': False}
            logger.error(result['message'])
        except RequestException as e:
            result = {'code':3,'message':'调用[%s]时发生Requests异常，异常原因：%s' % (requests_info['接口名称'], e.__str__()),'check_result': False}
            logger.error(result['message'])
        except Exception as e:
            result = {'code':3,'message':'调用[%s]时发生系统异常，异常原因：%s' % (requests_info['接口名称'], e.__str__()),'check_result': False}
            logger.error(result['message'])
        return result
    def request(self,requests_info):
        with allure.step('%s 开始调用'%requests_info['接口名称']):
            logger.info('%s 开始调用'%requests_info['接口名称'])
        request_type = requests_info['请求方式']
        if request_type == "get":
            result = self.__get( requests_info )
        elif request_type == "post":
            result = self.__post( requests_info )
        else:
            result = {'code':1,'message':'调用[%s]时,该接口的请求方式暂时不支持'%requests_info['接口名称'],'check_result':False}
            logger.error(result['message'])
        with allure.step('%s 调用结束' % requests_info['接口名称']):
            logger.info('%s 调用结束' % requests_info['接口名称'])
        return result
    # 多接口运行方法
    def request_by_step(self,test_steps): # test_steps为列表数据
        for test_step in test_steps:
            result = self.request(test_step)
            if result['code'] != 0:
                break
        return result

if  __name__=="__main__":
    # r_dict = {'测试用例编号': 'api_case_01', '测试用例名称': '获取access_token接口测试', '用例执行': '是', '用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求头部信息': '', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"wx55614004f367f8ca","secret":"65515b46dd758dfdb09420bb7db2c67f"}', '请求参数(post)': '', '取值方式': '无', '取值代码': '', '取值变量': '', '断言类型': 'body_regexp', '期望结果': '"access_token":"(.+?)"'}
    # u = RequestsUtils().request(r_dict)
    # print( u )
    # r_list = [{'测试用例编号': 'api_case_01', '测试用例名称': '获取access_token接口测试', '用例执行': '是', '用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求头部信息': '', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"wx55614004f367f8ca","secret":"65515b46dd758dfdb09420bb7db2c67f"}', '请求参数(post)': '', '取值方式': '无', '取值代码': '', '取值变量': '', '断言类型': 'body_regexp', '期望结果': '"access_token":"(.+?)"'}]
    r_list = [
        {'测试用例编号': 'api_case_02', '测试用例名称': '创建标签接口测试', '用例执行': '是', '用例步骤': 'step_01', '接口名称': '获取access_token接口', '请求方式': 'get', '请求头部信息': '', '请求地址': '/cgi-bin/token', '请求参数(get)': '{"grant_type":"client_credential","appid":"wx55614004f367f8ca","secret":"65515b46dd758dfdb09420bb7db2c67f"}', '请求参数(post)': '', '取值方式': '正则取值', '取值代码': '"access_token":"(.+?)"', '取值变量': 'token_value', '断言类型': 'body_regexp', '期望结果': '"access_token":"(.+?)"'},
		{'测试用例编号': 'api_case_02', '测试用例名称': '创建标签接口测试', '用例执行': '是', '用例步骤': 'step_02', '接口名称': '创建标签接口', '请求方式': 'post', '请求头部信息': '', '请求地址': '/cgi-bin/tags/create', '请求参数(get)': '{"access_token":"${token_value}"}', '请求参数(post)': '{   "tag" : {     "name" : "newP18" } } ', '取值方式': '无', '取值代码': '', '取值变量': '', '断言类型': 'json_key_value', '期望结果': '{"errcode":45056}'}
    ]
    u = RequestsUtils().request_by_step( r_list )
    print( u )
